# -*- coding:utf-8 -*-
# created on 2017/4/30
# 
from mathsolver.functions.base import *
from mathsolver.functions.base.base import new_latex
from mathsolver.functions.mathematica.mathematicaSolve import MathematicaSolve, MathematicaSimplify
from mathsolver.functions.process import ProcessExpression
from mathsolver.functions.xiangliang.Vector_SiBianXing.Vector_Quadra_Axis_Update import (XLBuildSquareAxis,
                                                                                         XLBuildDiamondAxis,
                                                                                         XLBuildRectangleAxis)
from mathsolver.functions.xiangliang.Vector_SiBianXing.base import (XLQuadraKnownUpdate,
                                                                    XLQuadraAxisConditionEqTransform)
from mathsolver.functions.xiangliang.basic import xl_solutions_subs, xl_search_multiple


class XLQuadraGetExpress001(BaseFunction):
    """
    已知正方形ABCD的边长为2,E为CD的中点,则\\overrightarrow{AE}•\\overrightarrow{BD}=().
    1.正方形类
    2.vEqs非空
    3.坐标法
    """
    def solver(self, *args):
        assert len(args) == 2
        p1, p2, p3, p4 = args[0].value
        name = p1 + p2 + p3 + p4
        assert name in self.known
        quadra = self.search(name)
        assert quadra
        quadra_type = quadra.type
        assert quadra_type == "vSquare"
        new_known = dict(self.known)
        stepsolver1 = XLBuildSquareAxis(new_known).solver(name)
        self.steps += stepsolver1.steps
        self.label.update(stepsolver1.label)
        quadra = stepsolver1.output[0]
        target = args[1].sympify()
        v_eqs = quadra.Eqs
        u_eqs = [[target, 0]]
        u_eqs.extend(v_eqs)
        stepsolver2 = XLQuadraKnownUpdate(new_known).solver(u_eqs, quadra)
        self.steps += stepsolver2.steps
        new_known = stepsolver2.output[0]
        condition_veqs = []
        for eq in v_eqs:
            if len(eq) == 2:
                new_eqs = XLQuadraAxisConditionEqTransform(new_known).solver(BaseEq(eq)).output[0].sympify()
            else:
                new_eqs = XLQuadraAxisConditionEqTransform(new_known).solver(BaseIneq(eq)).output[0].sympify()
            condition_veqs.extend(new_eqs)
        self.steps.append(["", "依题意，得"])
        if len(condition_veqs) == 1:
            if len(condition_veqs[0]) == 2:
                self.steps.append(["", "%s" % BaseEq(condition_veqs[0]).printing()])
            else:
                self.steps.append(["", "%s" % BaseIneq(condition_veqs[0]).printing()])
        else:
            self.steps.append(["", "%s" % BaseIneqs(condition_veqs).printing()])
        solutions = MathematicaSolve().solver(BaseIneqs(condition_veqs)).output[0]
        self.steps.append(["", "解得: %s" % (solutions.printing())])
        condition_target = ProcessExpression(new_known).solver(BaseValue(str(target))).output[0].sympify()
        if isinstance(args[0], BaseVector):
            left = condition_target[0]
            left_answers = xl_search_multiple(solutions, left)
            assert left_answers
            left_values = []
            for left_answer in left_answers:
                new_left = left
                new_left = new_left.subs(left_answer)
                if len(str(new_left)) > 15:
                    new_left = MathematicaSimplify().solver(BasePoly(new_left)).output[0].sympify()
                left_values.append(new_left)
            left_values = set(left_values)
            left_values = list(left_values)
            right = condition_target[1]
            right_answers = xl_search_multiple(solutions, right)
            assert right_answers
            right_values = []
            for right_answer in right_answers:
                new_right = right
                new_right = new_right.subs(right_answer)
                if len(str(new_right)) > 15:
                    new_right = MathematicaSimplify().solver(BasePoly(new_right)).output[0].sympify()
                right_values.append(new_right)
            right_values = set(right_values)
            right_values = list(right_values)
            tmp1 = new_latex(target)
            tmp2 = "或".join(["(%s, %s)" % (new_latex(left_v), new_latex(right_v)) for left_v, right_v in zip(
                left_values, right_values)])
            self.steps.append(["", "∴%s为%s" % (tmp1, tmp2)])
            target_values = []
            for left_v, right_v in zip(left_values, right_values):
                target_values.append([left_v, right_v])
            self.output.append(BaseVector(target_values))
        else:
            target_values = xl_solutions_subs(solutions, condition_target)
            tmp1 = " 或 ".join(["%s = %s" % (new_latex(target), new_latex(v)) for v in target_values])
            self.steps.append(["", "∴ %s" % tmp1])
            self.output.append(BaseNumbers(target_values))
        self.label.add("向量运算-坐标法")
        return self


class XLQuadraGetExpress002(BaseFunction):
    """
    已知菱形ABCD的边长为a,\\angle ABC=60°,则\\overrightarrow{BD}•\\overrightarrow{CD}= ()
    1.菱形类
    2.vEqs非空
    3.坐标法
    """
    def solver(self, *args):
        assert len(args) == 2
        p1, p2, p3, p4 = args[0].value
        name = p1 + p2 + p3 + p4
        assert name in self.known
        quadra = self.search(name)
        assert quadra
        quadra_type = quadra.type
        assert quadra_type == "vDiamond"
        new_known = dict(self.known)
        stepsolver1 = XLBuildDiamondAxis(new_known).solver(name)
        self.steps += stepsolver1.steps
        self.label.update(stepsolver1.label)
        quadra = stepsolver1.output[0]
        target = args[1].sympify()
        v_eqs = quadra.Eqs
        u_eqs = [[target, 0]]
        u_eqs.extend(v_eqs)
        stepsolver2 = XLQuadraKnownUpdate(new_known).solver(u_eqs, quadra)
        self.steps += stepsolver2.steps
        new_known = stepsolver2.output[0]
        condition_veqs = []
        for eq in v_eqs:
            if len(eq) == 2:
                new_eqs = XLQuadraAxisConditionEqTransform(new_known).solver(BaseEq(eq)).output[0].sympify()
            else:
                new_eqs = XLQuadraAxisConditionEqTransform(new_known).solver(BaseIneq(eq)).output[0].sympify()
            condition_veqs.extend(new_eqs)
        self.steps.append(["", "依题意，得"])
        if len(condition_veqs) == 1:
            if len(condition_veqs[0]) == 2:
                self.steps.append(["", "%s" % BaseEq(condition_veqs[0]).printing()])
            else:
                self.steps.append(["", "%s" % BaseIneq(condition_veqs[0]).printing()])
        else:
            self.steps.append(["", "%s" % BaseIneqs(condition_veqs).printing()])
        solutions = MathematicaSolve().solver(BaseIneqs(condition_veqs)).output[0]
        self.steps.append(["", "解得: %s" % (solutions.printing())])
        condition_target = ProcessExpression(new_known).solver(BaseValue(str(target))).output[0].sympify()
        if isinstance(args[0], BaseVector):
            left = condition_target[0]
            left_values = xl_solutions_subs(solutions, left)
            right = condition_target[1]
            right_values = xl_solutions_subs(solutions, right)
            tmp1 = new_latex(target)
            tmp2 = ["(%s, %s)" % (new_latex(left_v), new_latex(right_v))
                    for left_v, right_v in zip(left_values, right_values)]
            tmp2 = "或".join(tmp2)
            self.steps.append(["", "∴%s为%s" % (tmp1, tmp2)])
            target_values = []
            for left_v, right_v in zip(left_values, right_values):
                target_values.append([left_v, right_v])
            self.output.append(BaseVector(target_values))
        else:
            target_values = xl_solutions_subs(solutions, condition_target)
            self.steps.append(["", "∴ %s"
                               % " 或 ".join(["%s = %s" % (new_latex(target), new_latex(v)) for v in target_values])])
            self.output.append(BaseNumbers(target_values))
        self.label.add("向量运算-坐标法")
        return self


class XLQuadraGetExpress003(BaseFunction):
    """
    已知矩形ABCD,|\\overrightarrow{AB}|=6,|\\overrightarrow{AD}|=4.\\overrightarrow{BM}=3\\overrightarrow{MC},
    \\overrightarrow{DN}=2\\overrightarrow{NC},则\\overrightarrow{AM}•\\overrightarrow{NM}= ()
    1.矩形类
    2.vEqs非空
    3.坐标法
    """
    def solver(self, *args):
        assert len(args) == 2
        p1, p2, p3, p4 = args[0].value
        name = p1 + p2 + p3 + p4
        assert name in self.known
        quadra = self.search(name)
        assert quadra
        quadra_type = quadra.type
        assert quadra_type == "vRectangle"
        new_known = dict(self.known)
        stepsolver1 = XLBuildRectangleAxis(new_known).solver(name)
        self.steps += stepsolver1.steps
        self.label.update(stepsolver1.label)
        quadra = stepsolver1.output[0]
        target = args[1].sympify()
        v_eqs = quadra.Eqs
        u_eqs = [[target, 0]]
        u_eqs.extend(v_eqs)
        stepsolver2 = XLQuadraKnownUpdate(new_known).solver(u_eqs, quadra)
        self.steps += stepsolver2.steps
        new_known = stepsolver2.output[0]
        condition_veqs = []
        for eq in v_eqs:
            if len(eq) == 2:
                new_eqs = XLQuadraAxisConditionEqTransform(new_known).solver(BaseEq(eq)).output[0].sympify()
            else:
                new_eqs = XLQuadraAxisConditionEqTransform(new_known).solver(BaseIneq(eq)).output[0].sympify()
            condition_veqs.extend(new_eqs)
        self.steps.append(["", "依题意，得"])
        if len(condition_veqs) == 1:
            if len(condition_veqs[0]) == 2:
                self.steps.append(["", "%s" % BaseEq(condition_veqs[0]).printing()])
            else:
                self.steps.append(["", "%s" % BaseIneq(condition_veqs[0]).printing()])
        else:
            self.steps.append(["", "%s" % BaseIneqs(condition_veqs).printing()])
        solutions = MathematicaSolve().solver(BaseIneqs(condition_veqs)).output[0]
        self.steps.append(["", "解得: %s" % (solutions.printing())])
        condition_target = ProcessExpression(new_known).solver(BaseValue(str(target))).output[0].sympify()
        if isinstance(args[0], BaseVector):
            left = condition_target[0]
            left_values = xl_solutions_subs(solutions, left)
            right = condition_target[1]
            right_values = xl_solutions_subs(solutions, right)
            tmp1 = new_latex(target)
            tmp2 = ["(%s, %s)" % (new_latex(left_v), new_latex(right_v))
                    for left_v, right_v in zip(left_values, right_values)]
            self.steps.append(["", "∴%s为%s" % (tmp1, "或".join(tmp2))])
            target_values = []
            for left_v, right_v in zip(left_values, right_values):
                target_values.append([left_v, right_v])
            self.output.append(BaseVector(target_values))
        else:
            target_values = xl_solutions_subs(solutions, condition_target)
            self.steps.append(["", "∴ %s"
                               % " 或 ".join(["%s = %s" % (new_latex(target), new_latex(v)) for v in target_values])])
            self.output.append(BaseNumbers(target_values))
        self.label.add("向量运算-坐标法")
        return self


class XLQuadraGetExpress004(BaseFunction):
    """
    在平行四边形ABCD中,|\\overrightarrow{AB}|=2,|\\overrightarrow{AD}|=2,∠DAB=π,则\\overrightarrow{AB}•\\overrightarrow{BD}=
    1.平行四边形类
    2.vEqs非空
    3.坐标法
    """
    def solver(self, *args):
        assert len(args) == 2
        p1, p2, p3, p4 = args[0].value
        name = p1 + p2 + p3 + p4
        assert name in self.known
        v_pxsbx = self.search(name)
        assert v_pxsbx
        v_pxsbx_type = v_pxsbx.type
        assert v_pxsbx_type == 'vQuadra'
        v_eqs = v_pxsbx.Eqs
        target = args[0].sympify()
        u_eqs = [[target, 0]]
        u_eqs.extend(v_eqs)
        new_known = XLQuadraKnownUpdate(self.known, u_eqs, v_pxsbx)
        condition_veqs = []
        for eq in v_eqs:
            if len(eq) == 2:
                new_eqs = XLQuadraAxisConditionEqTransform(new_known).solver(BaseEq(eq)).output[0].sympify()
            else:
                new_eqs = XLQuadraAxisConditionEqTransform(new_known).solver(BaseIneq(eq)).output[0].sympify()
            condition_veqs.extend(new_eqs)
        self.steps.append(["", "依题意，得"])
        if len(condition_veqs) == 1:
            if len(condition_veqs[0]) == 2:
                self.steps.append(["", "%s" % BaseEq(condition_veqs[0]).printing()])
            else:
                self.steps.append(["", "%s" % BaseIneq(condition_veqs[0]).printing()])
        else:
            self.steps.append(["", "%s" % BaseIneqs(condition_veqs).printing()])
        solutions = MathematicaSolve().solver(BaseIneqs(condition_veqs)).output[0]
        self.steps.append(["", "解得: %s" % (solutions.printing())])
        condition_target = ProcessExpression(new_known).solver(BaseValue(str(target))).output[0].sympify()
        if isinstance(args[0], BaseVector):
            left = condition_target[0]
            left_values = xl_solutions_subs(solutions, left)
            right = condition_target[1]
            right_values = xl_solutions_subs(solutions, right)
            tmp1 = new_latex(target)
            tmp2 = ["(%s, %s)" % (new_latex(left_v), new_latex(right_v))
                    for left_v, right_v in zip(left_values, right_values)]
            self.steps.append(["", "∴%s为%s" % (tmp1, "或".join(tmp2))])
            target_values = []
            for left_v, right_v in zip(left_values, right_values):
                target_values.append([left_v, right_v])
            self.output.append(BaseVector(target_values))
        else:
            target_values = xl_solutions_subs(solutions, condition_target)
            self.steps.append(["", "∴ %s"
                               % " 或 ".join(["%s = %s" % (new_latex(target), new_latex(v)) for v in target_values])])
            self.output.append(BaseNumbers(target_values))
        self.label.add("向量运算-坐标法")
        return self


class XLQuadraGetExpress(BaseFunction):
    CLS = [XLQuadraGetExpress001, XLQuadraGetExpress002, XLQuadraGetExpress003, XLQuadraGetExpress004]

    def solver(self, *args):
        known = self.known
        r = None
        for cl in XLQuadraGetExpress.CLS:
            try:
                r = cl(known, verbose=True).solver(*args)
                break
            except Exception:
                pass
        if not r:
            raise 'try fail'
        return r
